library(here)
library(tidyverse)
library(conflicted)
# library(easystats)

exoplanets <- read_csv(here("data", "exoplanet_catalog_080325.csv"))
Warning: One or more parsing issues, call `problems()` on your data frame for details, e.g.:
  dat <- vroom(...)
  problems(dat)Rows: 7418 Columns: 98── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (12): name, planet_status, publication, detection_type, mass_measurement_type, radius_measurement_type, alternate_names, molecules, star_name, star_sp_ty...
dbl  (83): mass, mass_error_min, mass_error_max, mass_sini, mass_sini_error_min, mass_sini_error_max, radius, radius_error_min, radius_error_max, orbital_peri...
lgl   (2): hot_point_lon, star_magnetic_field
date  (1): updated
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
exoplanets
library(skimr)
skim(exoplanets)
Warning: There was 1 warning in `dplyr::summarize()`.
ℹ In argument: `dplyr::across(tidyselect::any_of(variable_names), mangled_skimmers$funs)`.
ℹ In group 0: .
Caused by warning:
! There was 1 warning in `dplyr::summarize()`.
ℹ In argument: `dplyr::across(tidyselect::any_of(variable_names), mangled_skimmers$funs)`.
Caused by warning in `inline_hist()`:
! Variable contains Inf or -Inf value(s) that were converted to NA.
── Data Summary ────────────────────────
                           Values    
Name                       exoplanets
Number of rows             7418      
Number of columns          98        
_______________________              
Column type frequency:               
  character                12        
  Date                     1         
  logical                  2         
  numeric                  83        
________________________             
Group variables            None      
library(naniar)
gg_miss_var(exoplanets)

library(visdat)
vis_dat(exoplanets)

names(exoplanets)
 [1] "name"                       "planet_status"              "mass"                       "mass_error_min"             "mass_error_max"            
 [6] "mass_sini"                  "mass_sini_error_min"        "mass_sini_error_max"        "radius"                     "radius_error_min"          
[11] "radius_error_max"           "orbital_period"             "orbital_period_error_min"   "orbital_period_error_max"   "semi_major_axis"           
[16] "semi_major_axis_error_min"  "semi_major_axis_error_max"  "eccentricity"               "eccentricity_error_min"     "eccentricity_error_max"    
[21] "inclination"                "inclination_error_min"      "inclination_error_max"      "angular_distance"           "discovered"                
[26] "updated"                    "omega"                      "omega_error_min"            "omega_error_max"            "tperi"                     
[31] "tperi_error_min"            "tperi_error_max"            "tconj"                      "tconj_error_min"            "tconj_error_max"           
[36] "tzero_tr"                   "tzero_tr_error_min"         "tzero_tr_error_max"         "tzero_tr_sec"               "tzero_tr_sec_error_min"    
[41] "tzero_tr_sec_error_max"     "lambda_angle"               "lambda_angle_error_min"     "lambda_angle_error_max"     "impact_parameter"          
[46] "impact_parameter_error_min" "impact_parameter_error_max" "tzero_vr"                   "tzero_vr_error_min"         "tzero_vr_error_max"        
[51] "k"                          "k_error_min"                "k_error_max"                "temp_calculated"            "temp_calculated_error_min" 
[56] "temp_calculated_error_max"  "temp_measured"              "hot_point_lon"              "geometric_albedo"           "geometric_albedo_error_min"
[61] "geometric_albedo_error_max" "log_g"                      "publication"                "detection_type"             "mass_measurement_type"     
[66] "radius_measurement_type"    "alternate_names"            "molecules"                  "star_name"                  "ra"                        
[71] "dec"                        "mag_v"                      "mag_i"                      "mag_j"                      "mag_h"                     
[76] "mag_k"                      "star_distance"              "star_distance_error_min"    "star_distance_error_max"    "star_metallicity"          
[81] "star_metallicity_error_min" "star_metallicity_error_max" "star_mass"                  "star_mass_error_min"        "star_mass_error_max"       
[86] "star_radius"                "star_radius_error_min"      "star_radius_error_max"      "star_sp_type"               "star_age"                  
[91] "star_age_error_min"         "star_age_error_max"         "star_teff"                  "star_teff_error_min"        "star_teff_error_max"       
[96] "star_detected_disc"         "star_magnetic_field"        "star_alternate_names"      
library(janitor)
exoplanets %>% tabyl(planet_status)
 planet_status    n percent
     Confirmed 7418       1
library(data.table)
# options(repr.matrix.max.rows=100)
exoplanets %>% 
  add_prop_miss() %>%
  arrange(prop_miss_all) %>% 
  head(5) %>% 
  data.table::transpose(keep.names="column") -> preview

preview
# preview %>% View()

We have a lot of features: - Planet name - Mass (M jup) - Mass*sin(i) (M jup) - This describes minimum mass of the planet due to inclination effect - Radius (Rjup) - Period (day) - a / the average distance of the planet and its star - it’s in AU (astronomical units), which is the standard distance used for these types of things - 1 AU is the average distance tween the earth and the sun - e / eccentry of a planet (between 0 and 1) - represenets how much of a circle is the orbit - e = 0 means perfect circle, e > 1 means its not bound to the star - Discovery - year when it was discovered - update - year it was updated -

conflicts_prefer(dplyr::filter)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::filter over any other package.
exoplanets %>% 
  filter(name %>% str_like("%TOI-784%"))
conflicts_prefer(dplyr::filter)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::filter over any other package.
exoplanets %>% 
  filter(discovered == 2023)
exoplanets %>%
  mutate(
    ra_rad = ra,  # Convert RA to radians
    dec_rad = dec  # Convert Dec to radians
  ) %>% 
  ggplot(aes(x = ra_rad, y = dec_rad, color = dec)) +
  geom_point(size = 0.4) +
  coord_map("aitoff") +  # Apply Aitoff projection
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "none"  # Optionally remove legend
  )

library(dplyr)
library(plotly)

# Create a new column to distinguish Kepler exoplanets
exoplanets_3d <- exoplanets %>%
  mutate(
    ra_rad = ra * pi / 180,   # Convert RA from degrees to radians
    dec_rad = dec * pi / 180, # Convert Dec from degrees to radians
    x = cos(dec_rad) * cos(ra_rad), # Convert to Cartesian coordinates
    y = cos(dec_rad) * sin(ra_rad),
    z = sin(dec_rad),
    kepler_highlight = ifelse(grepl("Kepler", name), "Kepler", "Other"), # Highlight Kepler exoplanets
    hover_text = paste("Name: ", name) # Create custom hover text with the name of the exoplanet
  )

# Create an interactive 3D scatter plot with plotly
plot_ly(
  data = exoplanets_3d,
  x = ~x,
  y = ~y,
  z = ~z,
  color = ~kepler_highlight,  # Use the kepler_highlight column for color mapping
  colors = c("Other" = "red", "Kepler" = "blue"), # Color Kepler exoplanets blue, others gray
  text = ~hover_text, # Show the name of the exoplanet on hover
  type = "scatter3d",
  mode = "markers",
  marker = list(size = 0.5)
) %>%
  layout(
    title = "3D Sky Map of Exoplanets (Kepler Highlighted)",
    scene = list(
      xaxis = list(title = "X"),
      yaxis = list(title = "Y"),
      zaxis = list(title = "Z")
    )
  )
Warning: Ignoring 1 observationsWarning: Ignoring 1 observations
# Load necessary libraries
library(dplyr)
library(ggplot2)

# Use dplyr to prepare the data
exoplanets %>%
  mutate(
    x = angular_distance * cos(inclination * pi / 180),  # Convert to Cartesian coordinates
    y = angular_distance * sin(inclination * pi / 180)
  ) %>% 
  ggplot(aes(x = x, y = y)) +
  geom_point(size = 3, alpha = 0.7, color = "blue") +  # Exoplanets
  geom_point(aes(x = 0, y = 0), color = "red", size = 5) +  # Host star
  labs(
    x = "Relative X Position (arcseconds)",
    y = "Relative Y Position (arcseconds)",
    title = "Exoplanet Positions in the Sky"
  ) +
  theme_minimal() +
  theme(legend.position = "none")


# Assuming your data is loaded as 'exoplanets'
# Convert RA to degrees (if it's in hours:minutes:seconds format)
# If RA is already in degrees, skip this step
exoplanets %>%
  mutate(
    ra_deg = ra,  # Convert RA from hours to degrees (if needed)
    # Convert to polar coordinates for plotting
    # RA is mapped to theta (0-360 degrees)
    theta = ra_deg
  ) %>% 
ggplot(aes(x = theta, y = star_distance, color = mass)) +
  # Use coord_polar for circular plot
  coord_polar(start = 0, direction = -1) + # Start at 0 degrees, clockwise direction
  # Add concentric circles for distance reference
  geom_hline(yintercept = c(10, 100, 1000, 10000), 
             color = "gray", linetype = "solid", size = 0.3, alpha = 0.7) +
  # Add radial lines for angle reference
  geom_vline(xintercept = seq(0, 330, by = 30), 
             color = "gray", linetype = "solid", size = 0.3, alpha = 0.7) +
  # Plot the exoplanets
  geom_point(alpha = 0.8, size = 1) +
  # Use log scale for distance
  scale_y_log10(
    breaks = c(10, 100, 1000, 10000),
    labels = c("10 pc", "100 pc", "1000 pc", "10000 pc"),
    limits = c(1, 15000)
  ) +
  # Use log scale for mass colors
  scale_color_gradientn(
    colors = c("#1E90FF", "#32CD32", "#FFFF00", "#FFA500", "#FF4500", "#FF0000"),
    trans = "log10",
    breaks = c(0.0001, 0.001, 0.01, 0.1, 1, 10),
    labels = c("10⁻⁴", "10⁻³", "10⁻²", "10⁻¹", "10⁰", "10¹"),
    name = "Planetary Mass (MJup)"
  ) +
  # Remove grid and axis elements
  theme_minimal() +
  theme(
    axis.title = element_blank(),
    axis.text.y = element_blank(),
    axis.text.x = element_blank(),
    panel.grid = element_blank(),
    legend.position = "bottom",
    legend.box = "horizontal",
    plot.title = element_text(hjust = 0.5)
  ) +
  ggtitle("Exoplanet Distribution")

library(ggplot2)
library(dplyr)

# Assuming exoplanets is your dataframe
# First, let's prepare the data
# We need to convert RA and Dec to proper coordinates for plotting

exoplanets_plot <- exoplanets %>%
  # Convert RA to proper format if needed
  # If RA is in hours (0-24), convert to degrees (0-360)
  mutate(
    ra_deg = ra * 15,  # Assuming ra is in hours; if already in degrees, remove this line
    
    # For this type of projection, we need to map RA and Dec to x and y coordinates
    # This is a simple equatorial projection
    x = cos(dec * pi/180) * sin(ra_deg * pi/180),
    y = sin(dec * pi/180)
  )

# Create the plot
celestial_plot <- ggplot(exoplanets_plot, aes(x = x, y = y)) +
  # Add a circular boundary representing the celestial sphere
  annotate("path", 
           x = cos(seq(0, 2*pi, length.out = 100)), 
           y = sin(seq(0, 2*pi, length.out = 100)),
           color = "gray", size = 0.5) +
  
  # Add grid lines for declination
  lapply(c(-60, -30, 0, 30, 60), function(dec) {
    # For each declination, calculate the circle
    r <- cos(dec * pi/180)  # Radius of the circle
    
    # Only draw the part of the circle that's visible
    geom_path(data = data.frame(
      x = r * cos(seq(0, 2*pi, length.out = 100)),
      y = sin(dec * pi/180) * rep(1, 100)
    ), aes(x = x, y = y), color = "gray", size = 0.3, inherit.aes = FALSE)
  }) +
  
  # Add grid lines for right ascension
  lapply(seq(0, 330, by = 30), function(ra) {
    # Convert RA to radians
    ra_rad <- ra * pi/180
    
    # Draw line from center to edge
    geom_path(data = data.frame(
      x = cos(seq(-pi/2, pi/2, length.out = 100)) * sin(ra_rad),
      y = sin(seq(-pi/2, pi/2, length.out = 100))
    ), aes(x = x, y = y), color = "gray", size = 0.3, inherit.aes = FALSE)
  }) +
  
  # Add labels for declination
  lapply(c(-60, -30, 0, 30, 60, 90), function(dec) {
    r <- cos(dec * pi/180)
    if (dec != 90) {  # No need to label the pole
      annotate("text", x = 0, y = sin(dec * pi/180), 
               label = paste0(dec), color = "black", size = 3)
    }
  }) +
  
  # Add labels for right ascension
  lapply(seq(0, 330, by = 30), function(ra) {
    ra_rad <- ra * pi/180
    x_edge <- sin(ra_rad)
    y_edge <- 0
    
    annotate("text", x = 1.05 * x_edge, y = 1.05 * y_edge, 
             label = paste0(ra, "deg"), color = "black", size = 3)
  }) +
  
  # Add the exoplanet points
  geom_point(color = "red", size = 1, alpha = 0.8) +
  
  # Set aspect ratio to 1 for a circular plot
  coord_fixed() +
  
  # Remove axis labels and ticks
  theme_void() +
  
  # Add a title if needed
  ggtitle("Exoplanet Distribution - Celestial Sphere Projection")

celestial_plot

# Load necessary libraries
library(rgl)
library(dplyr)
library(stringr)

# Prepare the data
# We need to convert RA and Dec to 3D Cartesian coordinates
exoplanets_3d <- exoplanets %>%
  mutate(
    # Convert RA to degrees if needed (assuming ra is in hours)
    ra_deg = ra * 15,  # If already in degrees, skip this
    
    # Convert to radians for the calculations
    ra_rad = ra_deg * pi/180,
    dec_rad = dec * pi/180,
    
    # Convert to 3D Cartesian coordinates (unit sphere)
    # Standard spherical to Cartesian conversion
    x = cos(dec_rad) * cos(ra_rad),
    y = cos(dec_rad) * sin(ra_rad),
    z = sin(dec_rad),
    
    # Identify Kepler planets
    # This checks if the name contains "Kepler" or "KOI"
    is_kepler = str_detect(name, regex("kepler|koi", ignore_case = TRUE))
  )

# Start a new 3D plot
open3d()
wgl 
 15 
# Set the background to black for a space feel
bg3d(color = "black")

# Add a semi-transparent celestial sphere for reference
spheres3d(0, 0, 0, radius = 1, col = "gray", alpha = 0.1)

# Add grid lines for declination
for (dec in seq(-60, 60, by = 30)) {
  dec_rad <- dec * pi/180
  radius <- cos(dec_rad)
  
  # Create a circle at this declination
  theta <- seq(0, 2*pi, length.out = 100)
  x <- radius * cos(theta)
  y <- radius * sin(theta)
  z <- rep(sin(dec_rad), 100)
  
  lines3d(x, y, z, color = "gray", alpha = 0.5)
  
  # Add text label for this declination
  text3d(0, 0, sin(dec_rad), texts = paste0(dec, "deg"), color = "white", adj = c(1.1, 0.5))
}

# Add grid lines for right ascension
for (ra in seq(0, 330, by = 30)) {
  ra_rad <- ra * pi/180
  
  # Create a line from south pole to north pole
  dec_range <- seq(-pi/2, pi/2, length.out = 100)
  x <- cos(dec_range) * cos(ra_rad)
  y <- cos(dec_range) * sin(ra_rad)
  z <- sin(dec_range)
  
  lines3d(x, y, z, color = "gray", alpha = 0.5)
  
  # Add text label for this RA
  text3d(1.1 * cos(0) * cos(ra_rad), 
         1.1 * cos(0) * sin(ra_rad), 
         0, 
         texts = paste0(ra, "deg"), 
         color = "white")
}

# Filter out any rows with NA values
valid_planets <- exoplanets_3d %>%
  filter(!is.na(x) & !is.na(y) & !is.na(z))

# Split into Kepler and non-Kepler planets
kepler_planets <- valid_planets %>% filter(is_kepler)
other_planets <- valid_planets %>% filter(!is_kepler)

# Plot non-Kepler exoplanets
points3d(other_planets$x, other_planets$y, other_planets$z, 
         color = "red", size = 3, alpha = 0.8)

# Plot Kepler exoplanets with a special color
points3d(kepler_planets$x, kepler_planets$y, kepler_planets$z, 
         color = "cyan", size = 3, alpha = 0.8)

# Set initial viewpoint
view3d(theta = 20, phi = 20, zoom = 0.8)

# Add title
title3d("3D Exoplanet Distribution - Celestial Sphere", color = "white", line = 2)

# Add a legend
legend_x <- rep(1.5, 2)
legend_y <- c(0.2, -0.2)
legend_z <- rep(0, 2)
legend_colors <- c("red", "cyan")

# Add legend points
points3d(legend_x, legend_y, legend_z, size = 5, color = legend_colors)

# Add text labels
text3d(legend_x[1] + 0.1, legend_y[1], legend_z[1], 
       texts = "Other Planets", 
       color = "white", adj = 0)
text3d(legend_x[2] + 0.1, legend_y[2], legend_z[2], 
       texts = "Kepler Planets", 
       color = "white", adj = 0)

# Add interaction controls
par3d(mouseMode = c("trackball", "zoom", "fov", "pull"))
# Load necessary libraries
library(rgl)
library(dplyr)
library(stringr)

# Prepare the data
exoplanets_3d <- exoplanets %>%
  mutate(
    # Convert RA to degrees if needed
    ra_deg = ra * 15,  # Skip if already in degrees
    
    # Convert to radians for calculations
    ra_rad = ra_deg * pi/180,
    dec_rad = dec * pi/180,
    
    # Standard projection from spherical to Cartesian coordinates
    # This is what creates the view you want
    x = ra_rad,  # Simply use RA as x
    y = dec_rad, # Simply use Dec as y
    z = 0,       # All on same plane for 2D projection
    
    # Identify Kepler planets
    is_kepler = str_detect(name, regex("kepler|koi", ignore_case = TRUE))
  )

# Start a new plot
# For this visualization, let's use a 2D plot which may be easier to work with
# for this specific case
open3d()
wgl 
 16 
bg3d("black")

# Draw grid lines for RA in radians or degrees
# Convert to degrees for labeling
for (ra in seq(0, 330, by = 30)) {
  ra_rad = ra * pi/180
  lines3d(c(ra_rad, ra_rad), c(-pi/2, pi/2), c(0,0), color="gray", alpha=0.5)
  text3d(ra_rad, -pi/2-0.1, 0, texts=paste0(ra, "deg"), color="white")
}

# Draw grid lines for Dec
for (dec in seq(-60, 60, by = 30)) {
  dec_rad = dec * pi/180
  lines3d(c(0, 2*pi), c(dec_rad, dec_rad), c(0,0), color="gray", alpha=0.5)
  text3d(0-0.1, dec_rad, 0, texts=paste0(dec, "deg"), color="white", adj=c(1,0.5))
}

# Filter out any rows with NA values
valid_planets <- exoplanets_3d %>%
  filter(!is.na(x) & !is.na(y))

# Split into Kepler and non-Kepler planets
kepler_planets <- valid_planets %>% filter(is_kepler)
other_planets <- valid_planets %>% filter(!is_kepler)

# Plot non-Kepler exoplanets
points3d(other_planets$x, other_planets$y, other_planets$z, 
         color = "red", size = 3, alpha = 0.8)

# Plot Kepler exoplanets with a special color
points3d(kepler_planets$x, kepler_planets$y, kepler_planets$z, 
         color = "darkred", size = 5, alpha = 0.8)

# Set an appropriate viewpoint for this projection
view3d(theta = 0, phi = -90, zoom = 0.7, fov = 0)

# Add legend
legend_x <- c(2*pi+0.2, 2*pi+0.2)
legend_y <- c(0.2, -0.2)
legend_z <- c(0, 0)
legend_colors <- c("red", "darkred")

# Add legend points
points3d(legend_x, legend_y, legend_z, size = 3, color = legend_colors)

# Add text labels
text3d(legend_x[1] + 0.1, legend_y[1], legend_z[1], 
       texts = "Other Planets", color = "white", adj = 0)
text3d(legend_x[2] + 0.1, legend_y[2], legend_z[2], 
       texts = "Kepler Planets", color = "white", adj = 0)

# Add title
title3d("Exoplanet Sky Distribution", color="white", line=2)
exoplanets %>% names()
 [1] "name"                       "planet_status"              "mass"                       "mass_error_min"             "mass_error_max"            
 [6] "mass_sini"                  "mass_sini_error_min"        "mass_sini_error_max"        "radius"                     "radius_error_min"          
[11] "radius_error_max"           "orbital_period"             "orbital_period_error_min"   "orbital_period_error_max"   "semi_major_axis"           
[16] "semi_major_axis_error_min"  "semi_major_axis_error_max"  "eccentricity"               "eccentricity_error_min"     "eccentricity_error_max"    
[21] "inclination"                "inclination_error_min"      "inclination_error_max"      "angular_distance"           "discovered"                
[26] "updated"                    "omega"                      "omega_error_min"            "omega_error_max"            "tperi"                     
[31] "tperi_error_min"            "tperi_error_max"            "tconj"                      "tconj_error_min"            "tconj_error_max"           
[36] "tzero_tr"                   "tzero_tr_error_min"         "tzero_tr_error_max"         "tzero_tr_sec"               "tzero_tr_sec_error_min"    
[41] "tzero_tr_sec_error_max"     "lambda_angle"               "lambda_angle_error_min"     "lambda_angle_error_max"     "impact_parameter"          
[46] "impact_parameter_error_min" "impact_parameter_error_max" "tzero_vr"                   "tzero_vr_error_min"         "tzero_vr_error_max"        
[51] "k"                          "k_error_min"                "k_error_max"                "temp_calculated"            "temp_calculated_error_min" 
[56] "temp_calculated_error_max"  "temp_measured"              "hot_point_lon"              "geometric_albedo"           "geometric_albedo_error_min"
[61] "geometric_albedo_error_max" "log_g"                      "publication"                "detection_type"             "mass_measurement_type"     
[66] "radius_measurement_type"    "alternate_names"            "molecules"                  "star_name"                  "ra"                        
[71] "dec"                        "mag_v"                      "mag_i"                      "mag_j"                      "mag_h"                     
[76] "mag_k"                      "star_distance"              "star_distance_error_min"    "star_distance_error_max"    "star_metallicity"          
[81] "star_metallicity_error_min" "star_metallicity_error_max" "star_mass"                  "star_mass_error_min"        "star_mass_error_max"       
[86] "star_radius"                "star_radius_error_min"      "star_radius_error_max"      "star_sp_type"               "star_age"                  
[91] "star_age_error_min"         "star_age_error_max"         "star_teff"                  "star_teff_error_min"        "star_teff_error_max"       
[96] "star_detected_disc"         "star_magnetic_field"        "star_alternate_names"      
# check how many are missing
exoplanets %>% 
  select(ra, dec, angular_distance) %>% 
  mutate(ra = ra %>% is.na(), dec = dec %>% is.na(), angular_distance = angular_distance %>% is.na()) %>%
  summarise_all(mean) %>%
  gather(key="column", value="percentage")
# check which ones dont have ra
exoplanets %>% 
  filter(ra %>% is.na())
# remove any column with error in the name
exoplanets_r <- exoplanets %>% 
  select(-contains("error")) %>% 
  select(-planet_status, -updated)
exoplanets_r %>% names
 [1] "name"                    "mass"                    "mass_sini"               "radius"                  "orbital_period"          "semi_major_axis"        
 [7] "eccentricity"            "inclination"             "angular_distance"        "discovered"              "omega"                   "tperi"                  
[13] "tconj"                   "tzero_tr"                "tzero_tr_sec"            "lambda_angle"            "impact_parameter"        "tzero_vr"               
[19] "k"                       "temp_calculated"         "temp_measured"           "hot_point_lon"           "geometric_albedo"        "log_g"                  
[25] "publication"             "detection_type"          "mass_measurement_type"   "radius_measurement_type" "alternate_names"         "molecules"              
[31] "star_name"               "ra"                      "dec"                     "mag_v"                   "mag_i"                   "mag_j"                  
[37] "mag_h"                   "mag_k"                   "star_distance"           "star_metallicity"        "star_mass"               "star_radius"            
[43] "star_sp_type"            "star_age"                "star_teff"               "star_detected_disc"      "star_magnetic_field"     "star_alternate_names"   
exoplanets %>% 
  tabyl("detection_type")
                       detection_type    n      percent
                           Astrometry   46 0.0062011324
                  Astrometry, Imaging    1 0.0001348072
          Astrometry, Radial Velocity    3 0.0004044217
                              Imaging  922 0.1242922621
                  Imaging, Astrometry   49 0.0066055541
                   Imaging, Kinematic    2 0.0002696145
                       Imaging, Other   46 0.0062011324
           Imaging, Other, Astrometry    1 0.0001348072
            Imaging, Other, Kinematic    3 0.0004044217
             Imaging, Primary Transit    1 0.0001348072
 Imaging, Radial Velocity, Astrometry    1 0.0001348072
                            Kinematic    2 0.0002696145
                         Microlensing  313 0.0421946616
                                Other   42 0.0056619035
                       Other, Imaging    1 0.0001348072
            Other, Imaging, Kinematic    1 0.0001348072
               Other, Radial Velocity    1 0.0001348072
                      Primary Transit 4509 0.6078457805
          Primary Transit, Astrometry    1 0.0001348072
           Primary Transit, Kinematic    1 0.0001348072
     Primary Transit, Radial Velocity    7 0.0009436506
                 Primary Transit, TTV    2 0.0002696145
                      Radial Velocity 1145 0.1543542734
          Radial Velocity, Astrometry   99 0.0133459153
             Radial Velocity, Imaging    2 0.0002696145
     Radial Velocity, Primary Transit    7 0.0009436506
              Radial Velocity, Timing    1 0.0001348072
                                  TTV   32 0.0043138312
                               Timing  160 0.0215691561
                   Timing, Astrometry    1 0.0001348072
                    Timing, Kinematic   10 0.0013480723
                        Timing, Other    6 0.0008088434

Kepler

# filter by the kepler
exoplanets %>% 
  filter(name %>% str_like("%Kepler%")) %>% 
  tabyl("detection_type")
                   detection_type    n      percent
                            Other    6 0.0021574973
                  Primary Transit 2719 0.9777058612
             Primary Transit, TTV    2 0.0007191658
                  Radial Velocity   25 0.0089895721
 Radial Velocity, Primary Transit    1 0.0003595829
                              TTV   23 0.0082704063
                           Timing    5 0.0017979144
exoplanets
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShjb25mbGljdGVkKQ0KIyBsaWJyYXJ5KGVhc3lzdGF0cykNCg0KZXhvcGxhbmV0cyA8LSByZWFkX2NzdihoZXJlKCJkYXRhIiwgImV4b3BsYW5ldF9jYXRhbG9nXzA4MDMyNS5jc3YiKSkNCmV4b3BsYW5ldHMNCmBgYA0KDQoNCmBgYHtyfQ0KbGlicmFyeShza2ltcikNCnNraW0oZXhvcGxhbmV0cykNCmBgYA0KDQoNCmBgYHtyLGZpZy5hc3A9Mn0NCmxpYnJhcnkobmFuaWFyKQ0KZ2dfbWlzc192YXIoZXhvcGxhbmV0cykNCmBgYA0KDQoNCmBgYHtyLCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9MTB9DQpsaWJyYXJ5KHZpc2RhdCkNCnZpc19kYXQoZXhvcGxhbmV0cykNCmBgYA0KDQoNCmBgYHtyfQ0KbmFtZXMoZXhvcGxhbmV0cykNCmBgYA0KDQoNCmBgYHtyfQ0KbGlicmFyeShqYW5pdG9yKQ0KZXhvcGxhbmV0cyAlPiUgdGFieWwocGxhbmV0X3N0YXR1cykNCmBgYA0KDQoNCmBgYHtyfQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KIyBvcHRpb25zKHJlcHIubWF0cml4Lm1heC5yb3dzPTEwMCkNCmV4b3BsYW5ldHMgJT4lIA0KICBhZGRfcHJvcF9taXNzKCkgJT4lDQogIGFycmFuZ2UocHJvcF9taXNzX2FsbCkgJT4lIA0KICBoZWFkKDUpICU+JSANCiAgZGF0YS50YWJsZTo6dHJhbnNwb3NlKGtlZXAubmFtZXM9ImNvbHVtbiIpIC0+IHByZXZpZXcNCg0KcHJldmlldw0KIyBwcmV2aWV3ICU+JSBWaWV3KCkNCmBgYA0KDQpXZSBoYXZlIGEgbG90IG9mIGZlYXR1cmVzOg0KLSBQbGFuZXQgbmFtZQ0KLSBNYXNzIChNIGp1cCkNCi0gTWFzcypzaW4oaSkgKE0ganVwKQ0KICAtIFRoaXMgZGVzY3JpYmVzIG1pbmltdW0gbWFzcyBvZiB0aGUgcGxhbmV0IGR1ZSB0byBpbmNsaW5hdGlvbiBlZmZlY3QNCi0gUmFkaXVzIChSanVwKQ0KLSBQZXJpb2QgKGRheSkNCi0gYSAvIHRoZSBhdmVyYWdlIGRpc3RhbmNlIG9mIHRoZSBwbGFuZXQgYW5kIGl0cyBzdGFyDQogIC0gaXQncyBpbiBBVSAoYXN0cm9ub21pY2FsIHVuaXRzKSwgd2hpY2ggaXMgdGhlIHN0YW5kYXJkIGRpc3RhbmNlIHVzZWQgZm9yIHRoZXNlIHR5cGVzIG9mIHRoaW5ncw0KICAtIDEgQVUgaXMgdGhlIGF2ZXJhZ2UgZGlzdGFuY2UgdHdlZW4gdGhlIGVhcnRoIGFuZCB0aGUgc3VuDQotIGUgLyBlY2NlbnRyeSBvZiBhIHBsYW5ldCAoYmV0d2VlbiAwIGFuZCAxKQ0KICAtIHJlcHJlc2VuZXRzIGhvdyBtdWNoIG9mIGEgY2lyY2xlIGlzIHRoZSBvcmJpdA0KICAtIGUgPSAwIG1lYW5zIHBlcmZlY3QgY2lyY2xlLCBlID4gMSBtZWFucyBpdHMgbm90IGJvdW5kIHRvIHRoZSBzdGFyDQotIERpc2NvdmVyeSAtIHllYXIgd2hlbiBpdCB3YXMgZGlzY292ZXJlZA0KLSB1cGRhdGUgLSB5ZWFyIGl0IHdhcyB1cGRhdGVkDQotIA0KDQpgYGB7cn0NCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OmZpbHRlcikNCmV4b3BsYW5ldHMgJT4lIA0KICBmaWx0ZXIobmFtZSAlPiUgc3RyX2xpa2UoIiVUT0ktNzg0JSIpKQ0KYGBgDQoNCg0KYGBge3J9DQpjb25mbGljdHNfcHJlZmVyKGRwbHlyOjpmaWx0ZXIpDQpleG9wbGFuZXRzICU+JSANCiAgZmlsdGVyKGRpc2NvdmVyZWQgPT0gMjAyMykNCmBgYA0KDQpgYGB7cn0NCmV4b3BsYW5ldHMgJT4lDQogIG11dGF0ZSgNCiAgICByYV9yYWQgPSByYSwgICMgQ29udmVydCBSQSB0byByYWRpYW5zDQogICAgZGVjX3JhZCA9IGRlYyAgIyBDb252ZXJ0IERlYyB0byByYWRpYW5zDQogICkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSByYV9yYWQsIHkgPSBkZWNfcmFkLCBjb2xvciA9IGRlYykpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMC40KSArDQogIGNvb3JkX21hcCgiYWl0b2ZmIikgKyAgIyBBcHBseSBBaXRvZmYgcHJvamVjdGlvbg0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiAgIyBPcHRpb25hbGx5IHJlbW92ZSBsZWdlbmQNCiAgKQ0KYGBgDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbG90bHkpDQoNCiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiB0byBkaXN0aW5ndWlzaCBLZXBsZXIgZXhvcGxhbmV0cw0KZXhvcGxhbmV0c18zZCA8LSBleG9wbGFuZXRzICU+JQ0KICBtdXRhdGUoDQogICAgcmFfcmFkID0gcmEgKiBwaSAvIDE4MCwgICAjIENvbnZlcnQgUkEgZnJvbSBkZWdyZWVzIHRvIHJhZGlhbnMNCiAgICBkZWNfcmFkID0gZGVjICogcGkgLyAxODAsICMgQ29udmVydCBEZWMgZnJvbSBkZWdyZWVzIHRvIHJhZGlhbnMNCiAgICB4ID0gY29zKGRlY19yYWQpICogY29zKHJhX3JhZCksICMgQ29udmVydCB0byBDYXJ0ZXNpYW4gY29vcmRpbmF0ZXMNCiAgICB5ID0gY29zKGRlY19yYWQpICogc2luKHJhX3JhZCksDQogICAgeiA9IHNpbihkZWNfcmFkKSwNCiAgICBjb2xvciA9IGNhc2Vfd2hlbiggICMgQ3JlYXRlIGEgY29sdW1uIGZvciByZWQgd2hlbiBrZXBsZXIsIGJsdWUgb3RoZXJ3aXNlDQogICAgICBzdHJfZGV0ZWN0KG5hbWUsIHJlZ2V4KCJrZXBsZXJ8a29pIiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiAicmVkIiwNCiAgICAgIFRSVUUgfiAiYmx1ZSINCiAgICApLA0KICAgIGhvdmVyX3RleHQgPSBwYXN0ZSgiTmFtZTogIiwgbmFtZSkgIyBDcmVhdGUgY3VzdG9tIGhvdmVyIHRleHQgd2l0aCB0aGUgbmFtZSBvZiB0aGUgZXhvcGxhbmV0DQogICkNCg0KIyBDcmVhdGUgYW4gaW50ZXJhY3RpdmUgM0Qgc2NhdHRlciBwbG90IHdpdGggcGxvdGx5DQpwbG90X2x5KA0KICBkYXRhID0gZXhvcGxhbmV0c18zZCwNCiAgeCA9IH54LA0KICB5ID0gfnksDQogIHogPSB+eiwNCiAgY29sb3IgPSB+Y29sb3IsICAjIFVzZSB0aGUga2VwbGVyX2hpZ2hsaWdodCBjb2x1bW4gZm9yIGNvbG9yIG1hcHBpbmcNCiAgIyBjb2xvcnMgPSBjKCJPdGhlciIgPSAicmVkIiwgIktlcGxlciIgPSAiYmx1ZSIpLCAjIENvbG9yIEtlcGxlciBleG9wbGFuZXRzIGJsdWUsIG90aGVycyBncmF5DQogIHRleHQgPSB+aG92ZXJfdGV4dCwgIyBTaG93IHRoZSBuYW1lIG9mIHRoZSBleG9wbGFuZXQgb24gaG92ZXINCiAgdHlwZSA9ICJzY2F0dGVyM2QiLA0KICBtb2RlID0gIm1hcmtlcnMiLA0KICBtYXJrZXIgPSBsaXN0KHNpemUgPSAwLjUpDQopICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSAiM0QgU2t5IE1hcCBvZiBFeG9wbGFuZXRzIChLZXBsZXIgSGlnaGxpZ2h0ZWQpIiwNCiAgICBzY2VuZSA9IGxpc3QoDQogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiWCIpLA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlkiKSwNCiAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICJaIikNCiAgICApDQogICkNCg0KYGBgDQoNCg0KYGBge3J9DQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcw0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBVc2UgZHBseXIgdG8gcHJlcGFyZSB0aGUgZGF0YQ0KZXhvcGxhbmV0cyAlPiUNCiAgbXV0YXRlKA0KICAgIHggPSBhbmd1bGFyX2Rpc3RhbmNlICogY29zKGluY2xpbmF0aW9uICogcGkgLyAxODApLCAgIyBDb252ZXJ0IHRvIENhcnRlc2lhbiBjb29yZGluYXRlcw0KICAgIHkgPSBhbmd1bGFyX2Rpc3RhbmNlICogc2luKGluY2xpbmF0aW9uICogcGkgLyAxODApDQogICkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAwLjcsIGNvbG9yID0gImJsdWUiKSArICAjIEV4b3BsYW5ldHMNCiAgZ2VvbV9wb2ludChhZXMoeCA9IDAsIHkgPSAwKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDUpICsgICMgSG9zdCBzdGFyDQogIGxhYnMoDQogICAgeCA9ICJSZWxhdGl2ZSBYIFBvc2l0aW9uIChhcmNzZWNvbmRzKSIsDQogICAgeSA9ICJSZWxhdGl2ZSBZIFBvc2l0aW9uIChhcmNzZWNvbmRzKSIsDQogICAgdGl0bGUgPSAiRXhvcGxhbmV0IFBvc2l0aW9ucyBpbiB0aGUgU2t5Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCg0KYGBge3J9DQoNCiMgQXNzdW1pbmcgeW91ciBkYXRhIGlzIGxvYWRlZCBhcyAnZXhvcGxhbmV0cycNCiMgQ29udmVydCBSQSB0byBkZWdyZWVzIChpZiBpdCdzIGluIGhvdXJzOm1pbnV0ZXM6c2Vjb25kcyBmb3JtYXQpDQojIElmIFJBIGlzIGFscmVhZHkgaW4gZGVncmVlcywgc2tpcCB0aGlzIHN0ZXANCmV4b3BsYW5ldHMgJT4lDQogIG11dGF0ZSgNCiAgICByYV9kZWcgPSByYSwgICMgQ29udmVydCBSQSBmcm9tIGhvdXJzIHRvIGRlZ3JlZXMgKGlmIG5lZWRlZCkNCiAgICAjIENvbnZlcnQgdG8gcG9sYXIgY29vcmRpbmF0ZXMgZm9yIHBsb3R0aW5nDQogICAgIyBSQSBpcyBtYXBwZWQgdG8gdGhldGEgKDAtMzYwIGRlZ3JlZXMpDQogICAgdGhldGEgPSByYV9kZWcNCiAgKSAlPiUgDQpnZ3Bsb3QoYWVzKHggPSB0aGV0YSwgeSA9IHN0YXJfZGlzdGFuY2UsIGNvbG9yID0gbWFzcykpICsNCiAgIyBVc2UgY29vcmRfcG9sYXIgZm9yIGNpcmN1bGFyIHBsb3QNCiAgY29vcmRfcG9sYXIoc3RhcnQgPSAwLCBkaXJlY3Rpb24gPSAtMSkgKyAjIFN0YXJ0IGF0IDAgZGVncmVlcywgY2xvY2t3aXNlIGRpcmVjdGlvbg0KICAjIEFkZCBjb25jZW50cmljIGNpcmNsZXMgZm9yIGRpc3RhbmNlIHJlZmVyZW5jZQ0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKDEwLCAxMDAsIDEwMDAsIDEwMDAwKSwgDQogICAgICAgICAgICAgY29sb3IgPSAiZ3JheSIsIGxpbmV0eXBlID0gInNvbGlkIiwgc2l6ZSA9IDAuMywgYWxwaGEgPSAwLjcpICsNCiAgIyBBZGQgcmFkaWFsIGxpbmVzIGZvciBhbmdsZSByZWZlcmVuY2UNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gc2VxKDAsIDMzMCwgYnkgPSAzMCksIA0KICAgICAgICAgICAgIGNvbG9yID0gImdyYXkiLCBsaW5ldHlwZSA9ICJzb2xpZCIsIHNpemUgPSAwLjMsIGFscGhhID0gMC43KSArDQogICMgUGxvdCB0aGUgZXhvcGxhbmV0cw0KICBnZW9tX3BvaW50KGFscGhhID0gMC44LCBzaXplID0gMSkgKw0KICAjIFVzZSBsb2cgc2NhbGUgZm9yIGRpc3RhbmNlDQogIHNjYWxlX3lfbG9nMTAoDQogICAgYnJlYWtzID0gYygxMCwgMTAwLCAxMDAwLCAxMDAwMCksDQogICAgbGFiZWxzID0gYygiMTAgcGMiLCAiMTAwIHBjIiwgIjEwMDAgcGMiLCAiMTAwMDAgcGMiKSwNCiAgICBsaW1pdHMgPSBjKDEsIDE1MDAwKQ0KICApICsNCiAgIyBVc2UgbG9nIHNjYWxlIGZvciBtYXNzIGNvbG9ycw0KICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oDQogICAgY29sb3JzID0gYygiIzFFOTBGRiIsICIjMzJDRDMyIiwgIiNGRkZGMDAiLCAiI0ZGQTUwMCIsICIjRkY0NTAwIiwgIiNGRjAwMDAiKSwNCiAgICB0cmFucyA9ICJsb2cxMCIsDQogICAgYnJlYWtzID0gYygwLjAwMDEsIDAuMDAxLCAwLjAxLCAwLjEsIDEsIDEwKSwNCiAgICBsYWJlbHMgPSBjKCIxMOKBu+KBtCIsICIxMOKBu8KzIiwgIjEw4oG7wrIiLCAiMTDigbvCuSIsICIxMOKBsCIsICIxMMK5IiksDQogICAgbmFtZSA9ICJQbGFuZXRhcnkgTWFzcyAoTUp1cCkiDQogICkgKw0KICAjIFJlbW92ZSBncmlkIGFuZCBheGlzIGVsZW1lbnRzDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICBsZWdlbmQuYm94ID0gImhvcml6b250YWwiLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpDQogICkgKw0KICBnZ3RpdGxlKCJFeG9wbGFuZXQgRGlzdHJpYnV0aW9uIikNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQoNCiMgQXNzdW1pbmcgZXhvcGxhbmV0cyBpcyB5b3VyIGRhdGFmcmFtZQ0KIyBGaXJzdCwgbGV0J3MgcHJlcGFyZSB0aGUgZGF0YQ0KIyBXZSBuZWVkIHRvIGNvbnZlcnQgUkEgYW5kIERlYyB0byBwcm9wZXIgY29vcmRpbmF0ZXMgZm9yIHBsb3R0aW5nDQoNCmV4b3BsYW5ldHNfcGxvdCA8LSBleG9wbGFuZXRzICU+JQ0KICAjIENvbnZlcnQgUkEgdG8gcHJvcGVyIGZvcm1hdCBpZiBuZWVkZWQNCiAgIyBJZiBSQSBpcyBpbiBob3VycyAoMC0yNCksIGNvbnZlcnQgdG8gZGVncmVlcyAoMC0zNjApDQogIG11dGF0ZSgNCiAgICByYV9kZWcgPSByYSAqIDE1LCAgIyBBc3N1bWluZyByYSBpcyBpbiBob3VyczsgaWYgYWxyZWFkeSBpbiBkZWdyZWVzLCByZW1vdmUgdGhpcyBsaW5lDQogICAgDQogICAgIyBGb3IgdGhpcyB0eXBlIG9mIHByb2plY3Rpb24sIHdlIG5lZWQgdG8gbWFwIFJBIGFuZCBEZWMgdG8geCBhbmQgeSBjb29yZGluYXRlcw0KICAgICMgVGhpcyBpcyBhIHNpbXBsZSBlcXVhdG9yaWFsIHByb2plY3Rpb24NCiAgICB4ID0gY29zKGRlYyAqIHBpLzE4MCkgKiBzaW4ocmFfZGVnICogcGkvMTgwKSwNCiAgICB5ID0gc2luKGRlYyAqIHBpLzE4MCkNCiAgKQ0KDQojIENyZWF0ZSB0aGUgcGxvdA0KY2VsZXN0aWFsX3Bsb3QgPC0gZ2dwbG90KGV4b3BsYW5ldHNfcGxvdCwgYWVzKHggPSB4LCB5ID0geSkpICsNCiAgIyBBZGQgYSBjaXJjdWxhciBib3VuZGFyeSByZXByZXNlbnRpbmcgdGhlIGNlbGVzdGlhbCBzcGhlcmUNCiAgYW5ub3RhdGUoInBhdGgiLCANCiAgICAgICAgICAgeCA9IGNvcyhzZXEoMCwgMipwaSwgbGVuZ3RoLm91dCA9IDEwMCkpLCANCiAgICAgICAgICAgeSA9IHNpbihzZXEoMCwgMipwaSwgbGVuZ3RoLm91dCA9IDEwMCkpLA0KICAgICAgICAgICBjb2xvciA9ICJncmF5Iiwgc2l6ZSA9IDAuNSkgKw0KICANCiAgIyBBZGQgZ3JpZCBsaW5lcyBmb3IgZGVjbGluYXRpb24NCiAgbGFwcGx5KGMoLTYwLCAtMzAsIDAsIDMwLCA2MCksIGZ1bmN0aW9uKGRlYykgew0KICAgICMgRm9yIGVhY2ggZGVjbGluYXRpb24sIGNhbGN1bGF0ZSB0aGUgY2lyY2xlDQogICAgciA8LSBjb3MoZGVjICogcGkvMTgwKSAgIyBSYWRpdXMgb2YgdGhlIGNpcmNsZQ0KICAgIA0KICAgICMgT25seSBkcmF3IHRoZSBwYXJ0IG9mIHRoZSBjaXJjbGUgdGhhdCdzIHZpc2libGUNCiAgICBnZW9tX3BhdGgoZGF0YSA9IGRhdGEuZnJhbWUoDQogICAgICB4ID0gciAqIGNvcyhzZXEoMCwgMipwaSwgbGVuZ3RoLm91dCA9IDEwMCkpLA0KICAgICAgeSA9IHNpbihkZWMgKiBwaS8xODApICogcmVwKDEsIDEwMCkNCiAgICApLCBhZXMoeCA9IHgsIHkgPSB5KSwgY29sb3IgPSAiZ3JheSIsIHNpemUgPSAwLjMsIGluaGVyaXQuYWVzID0gRkFMU0UpDQogIH0pICsNCiAgDQogICMgQWRkIGdyaWQgbGluZXMgZm9yIHJpZ2h0IGFzY2Vuc2lvbg0KICBsYXBwbHkoc2VxKDAsIDMzMCwgYnkgPSAzMCksIGZ1bmN0aW9uKHJhKSB7DQogICAgIyBDb252ZXJ0IFJBIHRvIHJhZGlhbnMNCiAgICByYV9yYWQgPC0gcmEgKiBwaS8xODANCiAgICANCiAgICAjIERyYXcgbGluZSBmcm9tIGNlbnRlciB0byBlZGdlDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBkYXRhLmZyYW1lKA0KICAgICAgeCA9IGNvcyhzZXEoLXBpLzIsIHBpLzIsIGxlbmd0aC5vdXQgPSAxMDApKSAqIHNpbihyYV9yYWQpLA0KICAgICAgeSA9IHNpbihzZXEoLXBpLzIsIHBpLzIsIGxlbmd0aC5vdXQgPSAxMDApKQ0KICAgICksIGFlcyh4ID0geCwgeSA9IHkpLCBjb2xvciA9ICJncmF5Iiwgc2l6ZSA9IDAuMywgaW5oZXJpdC5hZXMgPSBGQUxTRSkNCiAgfSkgKw0KICANCiAgIyBBZGQgbGFiZWxzIGZvciBkZWNsaW5hdGlvbg0KICBsYXBwbHkoYygtNjAsIC0zMCwgMCwgMzAsIDYwLCA5MCksIGZ1bmN0aW9uKGRlYykgew0KICAgIHIgPC0gY29zKGRlYyAqIHBpLzE4MCkNCiAgICBpZiAoZGVjICE9IDkwKSB7ICAjIE5vIG5lZWQgdG8gbGFiZWwgdGhlIHBvbGUNCiAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAsIHkgPSBzaW4oZGVjICogcGkvMTgwKSwgDQogICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMChkZWMpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKQ0KICAgIH0NCiAgfSkgKw0KICANCiAgIyBBZGQgbGFiZWxzIGZvciByaWdodCBhc2NlbnNpb24NCiAgbGFwcGx5KHNlcSgwLCAzMzAsIGJ5ID0gMzApLCBmdW5jdGlvbihyYSkgew0KICAgIHJhX3JhZCA8LSByYSAqIHBpLzE4MA0KICAgIHhfZWRnZSA8LSBzaW4ocmFfcmFkKQ0KICAgIHlfZWRnZSA8LSAwDQogICAgDQogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMS4wNSAqIHhfZWRnZSwgeSA9IDEuMDUgKiB5X2VkZ2UsIA0KICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKHJhLCAiZGVnIiksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpDQogIH0pICsNCiAgDQogICMgQWRkIHRoZSBleG9wbGFuZXQgcG9pbnRzDQogIGdlb21fcG9pbnQoY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEsIGFscGhhID0gMC44KSArDQogIA0KICAjIFNldCBhc3BlY3QgcmF0aW8gdG8gMSBmb3IgYSBjaXJjdWxhciBwbG90DQogIGNvb3JkX2ZpeGVkKCkgKw0KICANCiAgIyBSZW1vdmUgYXhpcyBsYWJlbHMgYW5kIHRpY2tzDQogIHRoZW1lX3ZvaWQoKSArDQogIA0KICAjIEFkZCBhIHRpdGxlIGlmIG5lZWRlZA0KICBnZ3RpdGxlKCJFeG9wbGFuZXQgRGlzdHJpYnV0aW9uIC0gQ2VsZXN0aWFsIFNwaGVyZSBQcm9qZWN0aW9uIikNCg0KY2VsZXN0aWFsX3Bsb3QNCmBgYA0KDQpgYGB7cn0NCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzDQpsaWJyYXJ5KHJnbCkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHN0cmluZ3IpDQoNCiMgUHJlcGFyZSB0aGUgZGF0YQ0KIyBXZSBuZWVkIHRvIGNvbnZlcnQgUkEgYW5kIERlYyB0byAzRCBDYXJ0ZXNpYW4gY29vcmRpbmF0ZXMNCmV4b3BsYW5ldHNfM2QgPC0gZXhvcGxhbmV0cyAlPiUNCiAgbXV0YXRlKA0KICAgICMgQ29udmVydCBSQSB0byBkZWdyZWVzIGlmIG5lZWRlZCAoYXNzdW1pbmcgcmEgaXMgaW4gaG91cnMpDQogICAgcmFfZGVnID0gcmEgKiAxNSwgICMgSWYgYWxyZWFkeSBpbiBkZWdyZWVzLCBza2lwIHRoaXMNCiAgICANCiAgICAjIENvbnZlcnQgdG8gcmFkaWFucyBmb3IgdGhlIGNhbGN1bGF0aW9ucw0KICAgIHJhX3JhZCA9IHJhX2RlZyAqIHBpLzE4MCwNCiAgICBkZWNfcmFkID0gZGVjICogcGkvMTgwLA0KICAgIA0KICAgICMgQ29udmVydCB0byAzRCBDYXJ0ZXNpYW4gY29vcmRpbmF0ZXMgKHVuaXQgc3BoZXJlKQ0KICAgICMgU3RhbmRhcmQgc3BoZXJpY2FsIHRvIENhcnRlc2lhbiBjb252ZXJzaW9uDQogICAgeCA9IGNvcyhkZWNfcmFkKSAqIGNvcyhyYV9yYWQpLA0KICAgIHkgPSBjb3MoZGVjX3JhZCkgKiBzaW4ocmFfcmFkKSwNCiAgICB6ID0gc2luKGRlY19yYWQpLA0KICAgIA0KICAgICMgSWRlbnRpZnkgS2VwbGVyIHBsYW5ldHMNCiAgICAjIFRoaXMgY2hlY2tzIGlmIHRoZSBuYW1lIGNvbnRhaW5zICJLZXBsZXIiIG9yICJLT0kiDQogICAgaXNfa2VwbGVyID0gc3RyX2RldGVjdChuYW1lLCByZWdleCgia2VwbGVyfGtvaSIsIGlnbm9yZV9jYXNlID0gVFJVRSkpDQogICkNCg0KIyBTdGFydCBhIG5ldyAzRCBwbG90DQpvcGVuM2QoKQ0KDQojIFNldCB0aGUgYmFja2dyb3VuZCB0byBibGFjayBmb3IgYSBzcGFjZSBmZWVsDQpiZzNkKGNvbG9yID0gImJsYWNrIikNCg0KIyBBZGQgYSBzZW1pLXRyYW5zcGFyZW50IGNlbGVzdGlhbCBzcGhlcmUgZm9yIHJlZmVyZW5jZQ0Kc3BoZXJlczNkKDAsIDAsIDAsIHJhZGl1cyA9IDEsIGNvbCA9ICJncmF5IiwgYWxwaGEgPSAwLjEpDQoNCiMgQWRkIGdyaWQgbGluZXMgZm9yIGRlY2xpbmF0aW9uDQpmb3IgKGRlYyBpbiBzZXEoLTYwLCA2MCwgYnkgPSAzMCkpIHsNCiAgZGVjX3JhZCA8LSBkZWMgKiBwaS8xODANCiAgcmFkaXVzIDwtIGNvcyhkZWNfcmFkKQ0KICANCiAgIyBDcmVhdGUgYSBjaXJjbGUgYXQgdGhpcyBkZWNsaW5hdGlvbg0KICB0aGV0YSA8LSBzZXEoMCwgMipwaSwgbGVuZ3RoLm91dCA9IDEwMCkNCiAgeCA8LSByYWRpdXMgKiBjb3ModGhldGEpDQogIHkgPC0gcmFkaXVzICogc2luKHRoZXRhKQ0KICB6IDwtIHJlcChzaW4oZGVjX3JhZCksIDEwMCkNCiAgDQogIGxpbmVzM2QoeCwgeSwgeiwgY29sb3IgPSAiZ3JheSIsIGFscGhhID0gMC41KQ0KICANCiAgIyBBZGQgdGV4dCBsYWJlbCBmb3IgdGhpcyBkZWNsaW5hdGlvbg0KICB0ZXh0M2QoMCwgMCwgc2luKGRlY19yYWQpLCB0ZXh0cyA9IHBhc3RlMChkZWMsICJkZWciKSwgY29sb3IgPSAid2hpdGUiLCBhZGogPSBjKDEuMSwgMC41KSkNCn0NCg0KIyBBZGQgZ3JpZCBsaW5lcyBmb3IgcmlnaHQgYXNjZW5zaW9uDQpmb3IgKHJhIGluIHNlcSgwLCAzMzAsIGJ5ID0gMzApKSB7DQogIHJhX3JhZCA8LSByYSAqIHBpLzE4MA0KICANCiAgIyBDcmVhdGUgYSBsaW5lIGZyb20gc291dGggcG9sZSB0byBub3J0aCBwb2xlDQogIGRlY19yYW5nZSA8LSBzZXEoLXBpLzIsIHBpLzIsIGxlbmd0aC5vdXQgPSAxMDApDQogIHggPC0gY29zKGRlY19yYW5nZSkgKiBjb3MocmFfcmFkKQ0KICB5IDwtIGNvcyhkZWNfcmFuZ2UpICogc2luKHJhX3JhZCkNCiAgeiA8LSBzaW4oZGVjX3JhbmdlKQ0KICANCiAgbGluZXMzZCh4LCB5LCB6LCBjb2xvciA9ICJncmF5IiwgYWxwaGEgPSAwLjUpDQogIA0KICAjIEFkZCB0ZXh0IGxhYmVsIGZvciB0aGlzIFJBDQogIHRleHQzZCgxLjEgKiBjb3MoMCkgKiBjb3MocmFfcmFkKSwgDQogICAgICAgICAxLjEgKiBjb3MoMCkgKiBzaW4ocmFfcmFkKSwgDQogICAgICAgICAwLCANCiAgICAgICAgIHRleHRzID0gcGFzdGUwKHJhLCAiZGVnIiksIA0KICAgICAgICAgY29sb3IgPSAid2hpdGUiKQ0KfQ0KDQojIEZpbHRlciBvdXQgYW55IHJvd3Mgd2l0aCBOQSB2YWx1ZXMNCnZhbGlkX3BsYW5ldHMgPC0gZXhvcGxhbmV0c18zZCAlPiUNCiAgZmlsdGVyKCFpcy5uYSh4KSAmICFpcy5uYSh5KSAmICFpcy5uYSh6KSkNCg0KIyBTcGxpdCBpbnRvIEtlcGxlciBhbmQgbm9uLUtlcGxlciBwbGFuZXRzDQprZXBsZXJfcGxhbmV0cyA8LSB2YWxpZF9wbGFuZXRzICU+JSBmaWx0ZXIoaXNfa2VwbGVyKQ0Kb3RoZXJfcGxhbmV0cyA8LSB2YWxpZF9wbGFuZXRzICU+JSBmaWx0ZXIoIWlzX2tlcGxlcikNCg0KIyBQbG90IG5vbi1LZXBsZXIgZXhvcGxhbmV0cw0KcG9pbnRzM2Qob3RoZXJfcGxhbmV0cyR4LCBvdGhlcl9wbGFuZXRzJHksIG90aGVyX3BsYW5ldHMkeiwgDQogICAgICAgICBjb2xvciA9ICJyZWQiLCBzaXplID0gMywgYWxwaGEgPSAwLjgpDQoNCiMgUGxvdCBLZXBsZXIgZXhvcGxhbmV0cyB3aXRoIGEgc3BlY2lhbCBjb2xvcg0KcG9pbnRzM2Qoa2VwbGVyX3BsYW5ldHMkeCwga2VwbGVyX3BsYW5ldHMkeSwga2VwbGVyX3BsYW5ldHMkeiwgDQogICAgICAgICBjb2xvciA9ICJjeWFuIiwgc2l6ZSA9IDMsIGFscGhhID0gMC44KQ0KDQojIFNldCBpbml0aWFsIHZpZXdwb2ludA0KdmlldzNkKHRoZXRhID0gMjAsIHBoaSA9IDIwLCB6b29tID0gMC44KQ0KDQojIEFkZCB0aXRsZQ0KdGl0bGUzZCgiM0QgRXhvcGxhbmV0IERpc3RyaWJ1dGlvbiAtIENlbGVzdGlhbCBTcGhlcmUiLCBjb2xvciA9ICJ3aGl0ZSIsIGxpbmUgPSAyKQ0KDQojIEFkZCBhIGxlZ2VuZA0KbGVnZW5kX3ggPC0gcmVwKDEuNSwgMikNCmxlZ2VuZF95IDwtIGMoMC4yLCAtMC4yKQ0KbGVnZW5kX3ogPC0gcmVwKDAsIDIpDQpsZWdlbmRfY29sb3JzIDwtIGMoInJlZCIsICJjeWFuIikNCg0KIyBBZGQgbGVnZW5kIHBvaW50cw0KcG9pbnRzM2QobGVnZW5kX3gsIGxlZ2VuZF95LCBsZWdlbmRfeiwgc2l6ZSA9IDUsIGNvbG9yID0gbGVnZW5kX2NvbG9ycykNCg0KIyBBZGQgdGV4dCBsYWJlbHMNCnRleHQzZChsZWdlbmRfeFsxXSArIDAuMSwgbGVnZW5kX3lbMV0sIGxlZ2VuZF96WzFdLCANCiAgICAgICB0ZXh0cyA9ICJPdGhlciBQbGFuZXRzIiwgDQogICAgICAgY29sb3IgPSAid2hpdGUiLCBhZGogPSAwKQ0KdGV4dDNkKGxlZ2VuZF94WzJdICsgMC4xLCBsZWdlbmRfeVsyXSwgbGVnZW5kX3pbMl0sIA0KICAgICAgIHRleHRzID0gIktlcGxlciBQbGFuZXRzIiwgDQogICAgICAgY29sb3IgPSAid2hpdGUiLCBhZGogPSAwKQ0KDQojIEFkZCBpbnRlcmFjdGlvbiBjb250cm9scw0KcGFyM2QobW91c2VNb2RlID0gYygidHJhY2tiYWxsIiwgInpvb20iLCAiZm92IiwgInB1bGwiKSkNCmBgYA0KYGBge3J9DQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcw0KbGlicmFyeShyZ2wpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzdHJpbmdyKQ0KDQojIFByZXBhcmUgdGhlIGRhdGENCmV4b3BsYW5ldHNfM2QgPC0gZXhvcGxhbmV0cyAlPiUNCiAgbXV0YXRlKA0KICAgICMgQ29udmVydCBSQSB0byBkZWdyZWVzIGlmIG5lZWRlZA0KICAgIHJhX2RlZyA9IHJhICogMTUsICAjIFNraXAgaWYgYWxyZWFkeSBpbiBkZWdyZWVzDQogICAgDQogICAgIyBDb252ZXJ0IHRvIHJhZGlhbnMgZm9yIGNhbGN1bGF0aW9ucw0KICAgIHJhX3JhZCA9IHJhX2RlZyAqIHBpLzE4MCwNCiAgICBkZWNfcmFkID0gZGVjICogcGkvMTgwLA0KICAgIA0KICAgICMgU3RhbmRhcmQgcHJvamVjdGlvbiBmcm9tIHNwaGVyaWNhbCB0byBDYXJ0ZXNpYW4gY29vcmRpbmF0ZXMNCiAgICAjIFRoaXMgaXMgd2hhdCBjcmVhdGVzIHRoZSB2aWV3IHlvdSB3YW50DQogICAgeCA9IHJhX3JhZCwgICMgU2ltcGx5IHVzZSBSQSBhcyB4DQogICAgeSA9IGRlY19yYWQsICMgU2ltcGx5IHVzZSBEZWMgYXMgeQ0KICAgIHogPSAwLCAgICAgICAjIEFsbCBvbiBzYW1lIHBsYW5lIGZvciAyRCBwcm9qZWN0aW9uDQogICAgDQogICAgIyBJZGVudGlmeSBLZXBsZXIgcGxhbmV0cw0KICAgIGlzX2tlcGxlciA9IHN0cl9kZXRlY3QobmFtZSwgcmVnZXgoImtlcGxlcnxrb2kiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKQ0KICApDQoNCiMgU3RhcnQgYSBuZXcgcGxvdA0KIyBGb3IgdGhpcyB2aXN1YWxpemF0aW9uLCBsZXQncyB1c2UgYSAyRCBwbG90IHdoaWNoIG1heSBiZSBlYXNpZXIgdG8gd29yayB3aXRoDQojIGZvciB0aGlzIHNwZWNpZmljIGNhc2UNCm9wZW4zZCgpDQpiZzNkKCJibGFjayIpDQoNCiMgRHJhdyBncmlkIGxpbmVzIGZvciBSQSBpbiByYWRpYW5zIG9yIGRlZ3JlZXMNCiMgQ29udmVydCB0byBkZWdyZWVzIGZvciBsYWJlbGluZw0KZm9yIChyYSBpbiBzZXEoMCwgMzMwLCBieSA9IDMwKSkgew0KICByYV9yYWQgPSByYSAqIHBpLzE4MA0KICBsaW5lczNkKGMocmFfcmFkLCByYV9yYWQpLCBjKC1waS8yLCBwaS8yKSwgYygwLDApLCBjb2xvcj0iZ3JheSIsIGFscGhhPTAuNSkNCiAgdGV4dDNkKHJhX3JhZCwgLXBpLzItMC4xLCAwLCB0ZXh0cz1wYXN0ZTAocmEsICJkZWciKSwgY29sb3I9IndoaXRlIikNCn0NCg0KIyBEcmF3IGdyaWQgbGluZXMgZm9yIERlYw0KZm9yIChkZWMgaW4gc2VxKC02MCwgNjAsIGJ5ID0gMzApKSB7DQogIGRlY19yYWQgPSBkZWMgKiBwaS8xODANCiAgbGluZXMzZChjKDAsIDIqcGkpLCBjKGRlY19yYWQsIGRlY19yYWQpLCBjKDAsMCksIGNvbG9yPSJncmF5IiwgYWxwaGE9MC41KQ0KICB0ZXh0M2QoMC0wLjEsIGRlY19yYWQsIDAsIHRleHRzPXBhc3RlMChkZWMsICJkZWciKSwgY29sb3I9IndoaXRlIiwgYWRqPWMoMSwwLjUpKQ0KfQ0KDQojIEZpbHRlciBvdXQgYW55IHJvd3Mgd2l0aCBOQSB2YWx1ZXMNCnZhbGlkX3BsYW5ldHMgPC0gZXhvcGxhbmV0c18zZCAlPiUNCiAgZmlsdGVyKCFpcy5uYSh4KSAmICFpcy5uYSh5KSkNCg0KIyBTcGxpdCBpbnRvIEtlcGxlciBhbmQgbm9uLUtlcGxlciBwbGFuZXRzDQprZXBsZXJfcGxhbmV0cyA8LSB2YWxpZF9wbGFuZXRzICU+JSBmaWx0ZXIoaXNfa2VwbGVyKQ0Kb3RoZXJfcGxhbmV0cyA8LSB2YWxpZF9wbGFuZXRzICU+JSBmaWx0ZXIoIWlzX2tlcGxlcikNCg0KIyBQbG90IG5vbi1LZXBsZXIgZXhvcGxhbmV0cw0KcG9pbnRzM2Qob3RoZXJfcGxhbmV0cyR4LCBvdGhlcl9wbGFuZXRzJHksIG90aGVyX3BsYW5ldHMkeiwgDQogICAgICAgICBjb2xvciA9ICJyZWQiLCBzaXplID0gMywgYWxwaGEgPSAwLjgpDQoNCiMgUGxvdCBLZXBsZXIgZXhvcGxhbmV0cyB3aXRoIGEgc3BlY2lhbCBjb2xvcg0KcG9pbnRzM2Qoa2VwbGVyX3BsYW5ldHMkeCwga2VwbGVyX3BsYW5ldHMkeSwga2VwbGVyX3BsYW5ldHMkeiwgDQogICAgICAgICBjb2xvciA9ICJkYXJrcmVkIiwgc2l6ZSA9IDUsIGFscGhhID0gMC44KQ0KDQojIFNldCBhbiBhcHByb3ByaWF0ZSB2aWV3cG9pbnQgZm9yIHRoaXMgcHJvamVjdGlvbg0KdmlldzNkKHRoZXRhID0gMCwgcGhpID0gLTkwLCB6b29tID0gMC43LCBmb3YgPSAwKQ0KDQojIEFkZCBsZWdlbmQNCmxlZ2VuZF94IDwtIGMoMipwaSswLjIsIDIqcGkrMC4yKQ0KbGVnZW5kX3kgPC0gYygwLjIsIC0wLjIpDQpsZWdlbmRfeiA8LSBjKDAsIDApDQpsZWdlbmRfY29sb3JzIDwtIGMoInJlZCIsICJkYXJrcmVkIikNCg0KIyBBZGQgbGVnZW5kIHBvaW50cw0KcG9pbnRzM2QobGVnZW5kX3gsIGxlZ2VuZF95LCBsZWdlbmRfeiwgc2l6ZSA9IDMsIGNvbG9yID0gbGVnZW5kX2NvbG9ycykNCg0KIyBBZGQgdGV4dCBsYWJlbHMNCnRleHQzZChsZWdlbmRfeFsxXSArIDAuMSwgbGVnZW5kX3lbMV0sIGxlZ2VuZF96WzFdLCANCiAgICAgICB0ZXh0cyA9ICJPdGhlciBQbGFuZXRzIiwgY29sb3IgPSAid2hpdGUiLCBhZGogPSAwKQ0KdGV4dDNkKGxlZ2VuZF94WzJdICsgMC4xLCBsZWdlbmRfeVsyXSwgbGVnZW5kX3pbMl0sIA0KICAgICAgIHRleHRzID0gIktlcGxlciBQbGFuZXRzIiwgY29sb3IgPSAid2hpdGUiLCBhZGogPSAwKQ0KDQojIEFkZCB0aXRsZQ0KdGl0bGUzZCgiRXhvcGxhbmV0IFNreSBEaXN0cmlidXRpb24iLCBjb2xvcj0id2hpdGUiLCBsaW5lPTIpDQpgYGANCg0KDQoNCmBgYHtyfQ0KZXhvcGxhbmV0cyAlPiUgbmFtZXMoKQ0KYGBgDQoNCmBgYHtyfQ0KIyBjaGVjayBob3cgbWFueSBhcmUgbWlzc2luZw0KZXhvcGxhbmV0cyAlPiUgDQogIHNlbGVjdChyYSwgZGVjLCBhbmd1bGFyX2Rpc3RhbmNlKSAlPiUgDQogIG11dGF0ZShyYSA9IHJhICU+JSBpcy5uYSgpLCBkZWMgPSBkZWMgJT4lIGlzLm5hKCksIGFuZ3VsYXJfZGlzdGFuY2UgPSBhbmd1bGFyX2Rpc3RhbmNlICU+JSBpcy5uYSgpKSAlPiUNCiAgc3VtbWFyaXNlX2FsbChtZWFuKSAlPiUNCiAgZ2F0aGVyKGtleT0iY29sdW1uIiwgdmFsdWU9InBlcmNlbnRhZ2UiKQ0KYGBgDQoNCg0KYGBge3J9DQojIGNoZWNrIHdoaWNoIG9uZXMgZG9udCBoYXZlIHJhDQpleG9wbGFuZXRzICU+JSANCiAgZmlsdGVyKHJhICU+JSBpcy5uYSgpKQ0KYGBgDQoNCg0KYGBge3J9DQojIHJlbW92ZSBhbnkgY29sdW1uIHdpdGggZXJyb3IgaW4gdGhlIG5hbWUNCmV4b3BsYW5ldHNfciA8LSBleG9wbGFuZXRzICU+JSANCiAgc2VsZWN0KC1jb250YWlucygiZXJyb3IiKSkgJT4lIA0KICBzZWxlY3QoLXBsYW5ldF9zdGF0dXMsIC11cGRhdGVkKQ0KZXhvcGxhbmV0c19yICU+JSBuYW1lcw0KYGBgDQoNCg0KYGBge3J9DQpleG9wbGFuZXRzICU+JSANCiAgdGFieWwoImRldGVjdGlvbl90eXBlIikNCmBgYA0KIyMgS2VwbGVyDQoNCmBgYHtyfQ0KIyBmaWx0ZXIgYnkgdGhlIGtlcGxlcg0KZXhvcGxhbmV0cyAlPiUgDQogIGZpbHRlcihuYW1lICU+JSBzdHJfbGlrZSgiJUtlcGxlciUiKSkgJT4lIA0KICB0YWJ5bCgiZGV0ZWN0aW9uX3R5cGUiKQ0KYGBgDQoNCmBgYHtyfQ0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KZXhvcGxhbmV0cw0KYGBgDQoNCmBgYHtyfQ0KDQpgYGANCg0K